const { v4: uuidv4 } = require('uuid')
const express = require('express')
const app = express()

app.use(express.json())

const ioredis = require('ioredis')

// 建立连接
const redis = new ioredis({
  port: 6379,
  host: '192.168.56.101',
  showFriendlyErrorStack: true
})

const typeMap = {
  all: Math.round(Math.random()),
  male: 0,
  female: 1
}

// 扔出一个漂流瓶
// 参数：
  // time：漂流瓶扔出的时间戳，默认时设置为Date.now（）。
  // owner：漂流瓶主人，可以是用户名或用户id，但必须仅有一个。
  // type：漂流瓶类型，为male或female之一。
  // content：漂流瓶内容。
// 返回结果：
  // code：标识码，0代表错误，1代表正确。
  // msg：返回正确或错误时的信息。
app.post('/', async (req, res, next) => {
  try {
    const bottle = req.body

    // 获取客户端表单数据
    const { time, owner, type, content } = bottle

    // 数据验证
    if (!time || !owner || !type || !content) {
      return res.status(422).json({
        error: '请求参数不符合规则要求'
      })
    }

    if (!Object.keys(typeMap).includes(type)) {
      return res.status(422).json({
        error: '漂流瓶类型不符合规则要求'
      })
    }

    // 为每个漂流瓶随机生成一个不重复的 id
    const bottleId = uuidv4()

    // 根据漂流瓶类型的不同将漂流瓶保存到不同的数据库
    // 主要目的是为了方便使用 Redis 中的 randomkey 命令：该命令返回当前数据库中的一个随机键，不能加任何条件
    await redis.select(typeMap[type] || 0)
 
    // 将数据存为哈希
    await redis.hmset(bottleId, bottle)

    // 设置漂流瓶生存期为 1 天
    await redis.expire(bottleId, 60 * 60 * 24)

    res.status(201).json({
      code: 1,
      msg: '已扔出一个漂流瓶！'
    })
  } catch (err) {
    next(err)
  }

})

// 捡一个漂流瓶
// 参数：
  // user：捡漂流瓶的人的用户名或用户id，必须唯一。
  // type：漂流瓶类型，这里我们设置三种类型：all代表全部，male代表男性，female代表女性，默认时为all。
// 返回结果：
  // code：标识码，1代表成功，0代表出错。
  // msg：返回的信息，错误时返回错误的信息，成功时返回漂流瓶的信息：
  // time：漂流瓶扔出的时间戳。
  // owner：漂流瓶主人，可以是用户名或用户id，但必须仅有一个。
  // type：漂流瓶类型，为male或female之一。
  // content：漂流瓶内容。
app.get('/', async (req, res, next) => {
  try {
    const query = req.query
    // 获取客户端表单数据
    const { user, type } = query

    // 数据验证
    if (!user) {
      return res.status(422).json({
        error: '请求参数不符合规则要求'
      })
    }

    // 根据请求的瓶子类型到不同的数据库中取数据
    await redis.select(typeMap[type || 'all'])

    // 随机返回一个漂流瓶 ID
    const bottleId = await redis.randomkey()

    if (!bottleId) {
      res.status(200).json({
        message: '大海空空如也...'
      })
    }

    // 根据漂流瓶 ID 获取完整的漂流瓶信息
    const bottle = await redis.hgetall(bottleId)
    
    res.status(200).json({
      code: 1,
      ...bottle
    })

    // 从 Redis 中删除捡到的漂流瓶
    redis.del(bottleId)
  } catch (err) {
    next(err)
  }

})

// 统一处理异常
app.use((err, req, res, next) => {
  res.status(500).json({
    code: 0,
    msg: err.message
  })
})

app.listen(3000, () => {
  console.log('running...')
})
